package com.newlink.building.login.ui

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.provider.Settings
import android.view.Gravity
import android.view.View
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.ScaleAnimation
import android.widget.ImageView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.view.ViewCompat
import ceneax.app.lib.qrscan.QRScan
import ceneax.app.lib.qrscan.arch.IScanCallback
import ceneax.app.lib.qrscan.bean.ParseResult
import ceneax.app.lib.qrscan.widget.MultiResultsView
import com.alibaba.android.arouter.facade.annotation.Route
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.zxing.BinaryBitmap
import com.google.zxing.ChecksumException
import com.google.zxing.DecodeHintType
import com.google.zxing.FormatException
import com.google.zxing.MultiFormatReader
import com.google.zxing.NotFoundException
import com.google.zxing.RGBLuminanceSource
import com.google.zxing.Result
import com.google.zxing.common.GlobalHistogramBinarizer
import com.google.zxing.common.HybridBinarizer
import com.google.zxing.qrcode.QRCodeReader
import com.king.app.dialog.AppDialog
import com.king.app.dialog.AppDialogConfig
import com.king.mlkit.vision.barcode.BarcodeDecoder
import com.newlink.building.login.R
import com.newlink.building.login.databinding.ActivityScanerCodeBinding
import com.newlink.building.common_base.base.NL_BaseActivity
import com.newlink.building.common_base.base.NL_OnActivityCallback
import com.newlink.building.common_base.constant.NL_Key
import com.newlink.building.common_base.constant.Base_RouterPath
import com.newlink.building.common_base.ext.drawRect
import com.newlink.building.common_base.ext.getString
import com.newlink.building.common_base.utils.NLog
import com.newlink.building.common_base.widget.CustomMessageDialog
import java.io.IOException
import java.util.EnumMap


/**
 * @Author: admin
 * @Date: 2022/9/19
 * @Description:
 * @License:  Copyright  1998 Fanvil Technology Co., Ltd. All rights reserved.
 */
@Route(path = Base_RouterPath.PATH_SCAN)
class Module_Login_ScanActivityNL : NL_BaseActivity(), IScanCallback {
    val HINTS: Map<DecodeHintType, Any> = EnumMap(
        DecodeHintType::class.java
    )
    private var mQRScan: QRScan? = null
    private val REQUEST_PICK_IMAGE = 1
    private var mTitle = ""

    private lateinit var mBinding: ActivityScanerCodeBinding
    override fun attachLayoutRes(): View {
        mBinding = ActivityScanerCodeBinding.inflate(layoutInflater)
        return mBinding.root
    }

    override fun initData() {

        mTitle = intent.getString(NL_Key.EXTRA_TITLE, "")
        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        window.statusBarColor = Color.TRANSPARENT

        val windowInsetsController = ViewCompat.getWindowInsetsController(
            window.decorView
        )
        if (windowInsetsController != null) {
            windowInsetsController.isAppearanceLightStatusBars = false
        }
    }

    override fun initView() {

        if (mTitle.isNotEmpty()) {
            mBinding.scanTopBarTitle.text = mTitle
        }

        mQRScan = QRScan.Builder(this)
            .setQRPreviewView(findViewById(R.id.qrPreviewView))
            .setBarcodeFormats(Barcode.FORMAT_QR_CODE)
            .setScanCallback(this)
            .build()

        mBinding.scanLight.setOnClickListener {
            if (mQRScan!!.qrCamera.isTorchEnabled) {
                mQRScan!!.qrCamera.enableTorch(false)
                mBinding.scanLight.setImageResource(R.drawable.scan_light)
            } else {
                mQRScan!!.qrCamera.enableTorch(true)
                mBinding.scanLight.setImageResource(R.drawable.ceneax_app_lib_qrscan_icon_torch_enable)
            }
        }

        mBinding.scanGallery.setOnClickListener {
//            pickImageFromGallery()
            startPickPhoto()
        }

        scanAnimation(mBinding.captureScanLine)

        mBinding.scanTopBarRight.setOnClickListener {
            val intent = Intent(this, Module_Login_RegisterActivityNL::class.java)
            startActivity(intent)
        }

        mBinding.topBarBack.setOnClickListener {
            finish()
        }

        mBinding.scanLoginAccount.setOnClickListener {
            finish()
        }

    }

    private fun startPickPhoto() {
        val pickIntent = Intent(Intent.ACTION_PICK)
        pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*")
        startActivityForResult(pickIntent, REQUEST_PICK_IMAGE)
    }

    private fun scanAnimation(view: View) {
        val animation = ScaleAnimation(1.0f, 1.0f, 0.0f, 1.0f)
        animation.repeatCount = -1
        animation.repeatMode = Animation.RESTART
        animation.interpolator = LinearInterpolator()
        animation.duration = 1200
        view.startAnimation(animation)
    }

    override fun onPause() {
        super.onPause()
        mQRScan!!.qrCamera.enableTorch(false)
    }

    override fun onDestroy() {
        super.onDestroy()
        mQRScan!!.qrCamera.release()
        mQRScan!!.release()
    }

    /**
     * 扫码后的回调
     */
    override fun onResult(bitmap: Bitmap, results: Array<out ParseResult>) {
        if (results.size == 1) {
            bitmap.recycle()
            finishWithResult(results[0])
            return
        }
        val drawView = MultiResultsView(this, bitmap, *results)
        drawView.setBackgroundColor(Color.BLACK)
        drawView.tag = "multi_results_container"
        drawView.setOnSelectedListener { result: ParseResult? ->
            result?.let {
                this.finishWithResult(result)
            }
        }
        mBinding.captureContainter.addView(drawView)

        mQRScan!!.qrCamera.unBindAll()
    }

    private fun finishWithResult(result: ParseResult) {
        NLog.e("扫码信息为:${result.content}")
        val bundle = Bundle()
        bundle.putString("data", result.content)
        setResult(RESULT_OK, intent.putExtras(bundle))
        finish()
    }


    private fun pickImageFromGallery() {
        val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
        startActivityForResult(intent, REQUEST_PICK_IMAGE)
//        if (ActivityCompat.checkSelfPermission(
//                this,
//                Manifest.permission.READ_MEDIA_IMAGES
//            ) != PackageManager.PERMISSION_GRANTED
//        ) {
//            // Request the permission
//            requestPermissionLauncher.launch(Manifest.permission.READ_MEDIA_IMAGES)
//        } else {
//            val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
//            startActivityForResult(intent, REQUEST_PICK_IMAGE)
//        }

    }

    private val requestPermissionLauncher =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
            if (isGranted) {
                // Permission is granted, proceed with notification-related actions
                NLog.e("[LoginActivity] !!! post_notification permission granted !!!! ")
                val intent =
                    Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
                startActivityForResult(intent, REQUEST_PICK_IMAGE)
            } else {
                // Permission is denied, show a message to the user or take appropriate action
                NLog.e("[LoginActivity] !!! post_notification permission denied !!!! ")
                showPermissionRationale()
            }
        }

    private fun showPermissionRationale() {
        val alertDialog = AlertDialog.Builder(this)
            .setMessage(getString(R.string.permission_content_photo))
            .setPositiveButton(getString(R.string.app_need_allow_display_over_go)) { _, _ ->
                openAppSettings()
            }
            .setNegativeButton(getString(R.string.cancel_dialog_custom)) { _, _ ->
                finish()
            }
            .create()

        alertDialog.show()

        alertDialog.window?.run {
            attributes = attributes.apply {
                width = (windowManager.defaultDisplay.width * 0.95).toInt()
                gravity = Gravity.CENTER
            }
        }
    }

    private fun openAppSettings() {
        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
            data = Uri.fromParts("package", packageName, null)
        }
        startActivityForResult(intent, object : NL_OnActivityCallback {
            override fun onActivityResult(resultCode: Int, data: Intent?) {
                if (ActivityCompat.checkSelfPermission(
                        this@Module_Login_ScanActivityNL,
                        Manifest.permission.POST_NOTIFICATIONS
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    showPermissionRationale()
                }
            }

        })
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_PICK_IMAGE && resultCode == RESULT_OK) {
            if (data != null) {
                processPhoto(data?.data)
//                val imageUri = data.data
//                processImage(imageUri)
            }
        }
    }

    private fun processPhoto(data: Uri?) {
        data?.let {
            try {
                BarcodeDecoder.process(
                    BarcodeDecoder.fromFilePath(this@Module_Login_ScanActivityNL, it),
                    Barcode.FORMAT_QR_CODE
                ).addOnSuccessListener(this) { result ->

                    if (result.isNotEmpty()) {
                        val srcBitmap = MediaStore.Images.Media.getBitmap(contentResolver, it)
//                        showResultDialog(srcBitmap, result)
                        val buffer = StringBuilder()
                        for (barcode in result) {
                            buffer.append(barcode.displayValue)
                        }
                        val res = buffer.toString()
                        NLog.e("res =========> $res")
                        if (res.isNotEmpty()) {
                            handleQRCode(res)
                        } else {
                            showParseQrCodeErrorDialog()
                        }
                    } else {
                        NLog.e("result is empty")
                        showParseQrCodeErrorDialog()
                    }

                }.addOnFailureListener(this) { e ->
                    // 失败
                    NLog.e("$e")
                    showParseQrCodeErrorDialog()
                }
            } catch (e: Exception) {
                NLog.e("$e")
                showParseQrCodeErrorDialog()
            }
        }
    }

    private fun showParseQrCodeErrorDialog() {
        CustomMessageDialog(this).setMessage(getString(R.string.login_recognize_code))
            .setNegativeButton(
                resources.getString(R.string.confirm_dialog_custom),
                object : CustomMessageDialog.OnClickListener {
                    override fun onClick(dialog: CustomMessageDialog) {
                        dialog.dismiss()
                    }
                }
            ).setPositiveButton(null).show()
    }

    private fun showResultDialog(srcBitmap: Bitmap, result: List<Barcode>) {
        val buffer = StringBuilder()

        // 成功；在图片上框出结果
        val bitmap = srcBitmap.drawRect { canvas, paint ->
            for ((index, barcode) in result.withIndex()) {
                buffer.append("[$index] ").append(barcode.displayValue).append("\n")
                barcode.boundingBox?.let { box ->
                    canvas.drawRect(box, paint)
                }
            }
        }
        val config = AppDialogConfig(this@Module_Login_ScanActivityNL, R.layout.barcode_result_dialog)
        config.setContent(buffer).setHideCancel(true).setOnClickConfirm {
            AppDialog.INSTANCE.dismissDialog()
        }
        val imageView = config.getView<ImageView>(R.id.ivDialogContent)
        imageView.setImageBitmap(bitmap)
        AppDialog.INSTANCE.showDialog(config)
    }

    private fun processImage(imageUri: Uri?) {
        try {
            val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri)
            // 在这里将Bitmap对象传递给ZXing库进行二维码识别
//            decodeQRCode(bitmap)
            val res = syncDecodeQRCode(bitmap)
            NLog.e("[jake1] >>>  parse qrcode bitmap : $res")
            if (res != null) {
                handleQRCode(res)
            } else {
                CustomMessageDialog(this).setMessage(getString(R.string.login_recognize_code))
                    .setNegativeButton(
                        resources.getString(R.string.confirm_dialog_custom),
                        object : CustomMessageDialog.OnClickListener {
                            override fun onClick(dialog: CustomMessageDialog) {
                                dialog.dismiss()
                            }
                        }
                    ).setPositiveButton(null).show()

            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    fun syncDecodeQRCode(bitmap: Bitmap): String? {
        var result: Result? = null
        var source: RGBLuminanceSource? = null
        return try {
            val width = bitmap.width
            val height = bitmap.height
            val pixels = IntArray(width * height)
            bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
            source = RGBLuminanceSource(width, height, pixels)
            result = MultiFormatReader().decode(BinaryBitmap(HybridBinarizer(source)), HINTS)
            result.getText()
        } catch (e: Exception) {
            e.printStackTrace()
            if (source != null) {
                try {
                    result = MultiFormatReader().decode(
                        BinaryBitmap(GlobalHistogramBinarizer(source)),
                    )
                    return result.getText()
                } catch (e2: Throwable) {
                    e2.printStackTrace()
                }
            }
            null
        }
    }

    private fun decodeQRCode(bitmap: Bitmap) {
        try {
            val width = bitmap.width
            val height = bitmap.height
            val pixels = IntArray(width * height)
            bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
            val source = RGBLuminanceSource(width, height, pixels)
            val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
            val reader = QRCodeReader()
            val result = reader.decode(binaryBitmap)
            val qrCodeText: String = result.text

            // 在这里处理识别到的二维码文本
            handleQRCode(qrCodeText)
        } catch (e: NotFoundException) {
            e.printStackTrace()
        } catch (e: ChecksumException) {
            e.printStackTrace()
        } catch (e: FormatException) {
            e.printStackTrace()
        }
    }

    private fun handleQRCode(qrCodeText: String) {
        // 在这里处理识别到的二维码文本，如显示到界面上或进行其他操作
        NLog.e("扫码信息为:${qrCodeText}")
        val bundle = Bundle()
        bundle.putString("data", qrCodeText)
        setResult(RESULT_OK, intent.putExtras(bundle))
        finish()
    }
}